﻿/* ==============================================================================
*
*   Copyright (c) 2010, Pierre Favier
*   All rights reserved.
*
*   NTasking is free software: you can redistribute it and/or modify it
*   under the terms of the GNU General Public License as published by the
*   Free Software Foundation.
*
*   Redistribution and use in source and binary forms, with or without
*   modification, are permitted provided that the following conditions
*   are met:
*
*   -   Redistributions of source code must retain the above copyright notice,
*       this list of conditions and the following disclaimer.
*
*   -   Redistributions in binary form must reproduce the above
*       copyright notice, this list of conditions and the following
*       disclaimer in the documentation and/or other materials
*       provided with the distribution.
*
*   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
*   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
*   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
*   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
*   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
*   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
*   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
*   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
*   TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
*   THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
*   SUCH DAMAGE.
*
* ============================================================================== */

using NTasking.Internals;

namespace NTasking
{

    /// <summary>
    /// The <see cref="Settings"/> holds parameters used to tweak the behaviour of the runtime.
    /// </summary>
    public static class Settings
    {

        private static AdaCompatibilityMode _requeueMode = AdaCompatibilityMode.StrictCompatibility;

        private static AdaCompatibilityMode _acceptSelectPlacement = AdaCompatibilityMode.StrictCompatibility;

        private static QueueingPolicy _queueingPolicy = QueueingPolicy.FifoQueueing;

        private static bool _allowMultipleSelectiveCalls;


        /// <summary>
        /// Gets or Sets a value defining how Requeue statements are treated.
        /// </summary>
        /// <value>
        /// - When set to <c>AdaCompatibilityMode.StrictCompatibility</c> Requeue can only be performed
        ///   onto an entry which:
        ///     + has the same parameter number and parameter types as the currently accepted entry or has no parameters
        ///     + has the same return type as the currently accepted entry
        /// - When set to <c>AdaCompatibilityMode.RelaxedCompatibility</c> Requeue can be performed
        ///   onto an entry which:
        ///     + has any number parameters between 0 and the number of parameters of the currently accepted entry
        ///     + the parameter types are compatible : i.e. parameter types of the requeue target are identical
        ///       to the parameter type of the currently accepted entry or are of an ancestor class
        ///     + the return types are compatible : i.e. the return type of the requeue target is identical
        ///       to the return type of the currently accepted entry or is of a derived class or the currently
        ///       accepted entry has no return type (void)
        /// </value>
        /// <exception cref="System.InvalidOperationException">
        /// Thrown when the value is set after entering the top-level block
        /// </exception>
        public static AdaCompatibilityMode RequeueMode
        {
            get { return _requeueMode; }
            set
            {
                if (Block.Environment != null)
                    throw Errors.TaskingConfigurationNotChangeable();

                _requeueMode = value;
            }
        }

        
        /// <summary>
        /// Gets or Sets a value indicating where Accept and Select statements can appear within a <see cref="Task"/>
        /// </summary>
        /// <value>
        /// - When set to <c>AdaCompatibilityMode.StrictCompatibility</c> Select and Accept statements
        ///   can only appear inside a <see cref="Task"/> Body
        /// - When set to <c>AdaCompatibilityMode.RelaxedCompatibility</c> Select and Accept statements
        ///   can appear outside of a <see cref="Task"/> Body
        /// </value>
        /// <exception cref="System.InvalidOperationException">
        /// Thrown when the value is set after entering the top-level block
        /// </exception>
        public static AdaCompatibilityMode AcceptSelectPlacement
        {
            get { return _acceptSelectPlacement; }
            set
            {
                if (Block.Environment != null)
                    throw Errors.TaskingConfigurationNotChangeable();

                _acceptSelectPlacement = value;
            }
        }


        /// <summary>
        /// Gets or Sets a value indicating how calls are queued onto entries.
        /// </summary>
        /// <value>
        /// - When set to <c>QueueingPolicy.FifoQueueing</c>, entry calls are queued in a first come
        ///   first serve order
        /// - When set to <c>QueueingPolicy.PriorityQueueing</c>, entry calls are queued in descending
        ///   order of the calling <see cref="Task"/> priority. Within a given priority entry calls
        ///   are queued in FIFO order.
        /// </value>
        /// <exception cref="System.InvalidOperationException">
        /// Thrown when the value is set after entering the top-level block
        /// </exception>
        public static QueueingPolicy QueueingPolicy
        {
            get { return _queueingPolicy; }
            set
            {
                if (Block.Environment != null)
                    throw Errors.TaskingConfigurationNotChangeable();

                _queueingPolicy = value;
            }
        }


        /// <summary>
        /// Gets or sets a value indicating whether multiple selective calls are allowed.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if multiple selective calls are allowed; otherwise, <c>false</c>.
        /// </value>
        public static bool AllowMultipleSelectiveCalls
        {
            get { return _allowMultipleSelectiveCalls; }
            set
            {
                if (Block.Environment != null)
                    throw Errors.TaskingConfigurationNotChangeable();

                _allowMultipleSelectiveCalls = value;
            }
        }

    }

}
